package com.wsoft.bpm.component.command;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiEngineAgenda;
import org.activiti.engine.impl.history.HistoryManager;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 多个节点跳转（动态加载process）
 *
 * @Author zhonglj
 * @Date 2024-11-07 10:33
 */
@Log4j2
@AllArgsConstructor
public class TaskJumpMultiCmd implements Command<Boolean> {
    private String taskId;
    private List<String> targetNodes;

    @Override
    public Boolean execute(CommandContext commandContext) {
        ActivitiEngineAgenda agenda = commandContext.getAgenda();
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
        HistoryManager historyManager = commandContext.getHistoryManager();

        TaskEntity taskEntity = taskEntityManager.findById(taskId);
        // 执行实例 id
        String executionId = taskEntity.getExecutionId();
        String processDefinitionId = taskEntity.getProcessDefinitionId();
        // 执行实例对象
        ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
        Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);

        // 验证每个 目标节点 是否存在
        List<FlowElement> toFlowElements = new ArrayList<>();
        for (String targetNode : targetNodes) {
            FlowElement toFlowElement = process.getFlowElement(targetNode);
            if (toFlowElement == null) {
                log.error("targetNode {} is not exist", targetNode);
                continue;
            }
            toFlowElements.add(toFlowElement);
        }

        if (toFlowElements.size() == 0) {
            log.error("targetNodes is all not exist");
            return false;
        }

        // 将历史活动表更新
        historyManager.recordActivityEnd(executionEntity, "任务动态跳转");
        // 从runtime 表中删除当前任务
        taskEntityManager.delete(taskId);
        // 将历史任务表更新, 历史任务标记为完成
        historyManager.recordTaskEnd(taskId, "任务动态跳转");

        // 为每个目标节点创建新的执行实例，并绑定到相应的目标节点
        for (FlowElement toFlowElement : toFlowElements) {
            ExecutionEntity childExecution = executionEntityManager.createChildExecution(executionEntity);
            childExecution.setCurrentFlowElement(toFlowElement);
            // 执行流程操作
            agenda.planContinueProcessOperation(childExecution);
        }

        return true;
    }
}
